#ifndef __SFTL
#define __SFTL

#include "type.h"
#include "pagemap.h"
#include "flash.h"

struct ftl_operation * sftl_setup();

#define SFTL_MF_INVALID 0
#define SFTL_MF_DISK    1
#define SFTL_MF_FLAT    2
#define SFTL_MF_COMPACT 3
#define SFTL_MF_GHOST   4

struct sftl_disk_table
{
	 unsigned int ppn[MAP_ENTRIES_PER_PAGE];
};

struct sftl_dir_entry
{
	 /* Whether is compact or flat or in disk */
	 unsigned char type;
	 /* dirty flag */
	 unsigned char dirty;
	 /* How many pages of the dir mapped to have been used */
	 unsigned int pages_used;
	 /* count of node in compact form */
	 unsigned int compact_size;
	 /* The actual mapping table */
	 unsigned int ppn[MAP_ENTRIES_PER_PAGE];
	 unsigned int mapping_ppn;
	 /* The double-linked struct for LRU stack */
	 int older, newer;
};

extern int sftl_oldest_dir;
extern int sftl_newest_dir;

extern struct sftl_dir_entry *sftl_dir;
extern unsigned char *sftl_valid_bitmap;
extern unsigned char *sftl_blk_valid_count;

extern unsigned int sftl_pages_count;
extern unsigned int sftl_blk_count;
extern unsigned int sftl_dir_count;

extern unsigned int sftl_free_blk;
extern unsigned int sftl_free_count;
extern unsigned int sftl_free_arr[PAGE_NUM_PER_BLK];

extern unsigned int sftl_compact_dir_count;
extern unsigned int sftl_total_compact_count;
extern unsigned int sftl_total_flat_count;
extern unsigned int sftl_total_limit;

extern unsigned int sftl_operation_count;
extern unsigned int sftl_stat_access_count;
extern unsigned int sftl_stat_hit_count;

#define SFTL_COMPACT_SIZE 20
#define SFTL_FLAT_SIZE 4
#define SFTL_TOTAL_LIMIT (1 << 15) // 32k

void sftl_mapping_clean();
void sftl_stat_reset();
void sftl_stat_bucket_push(double v);

// #define SFTL_DEBUG

#endif
